#pragma once
#include <bondlib/BondDeal/PanoramicBondDealStruct.h>
#include <core/sync/lock.h>
#include <qbmessage/include/message_bond.h>
#include <qbprotocol/include/SSFIModel.h>
#include <qbprotocol/include/SSQBModel.h>
#include <qbprotocol/include/SSMsgStruct.h>
#include <QString>
#include <set>
#include <map>
#include <list>
#include "bondlib/BondContainer.h"
#include "bondlib/SSVContainer.h"
#include <QList>

class CNewBondPanDeal : public sPanoramicBondDealUnit {
public:
	CNewBondPanDeal();

	bool addDeal(const sPanoramicBondDealUnit& unitD);		 //添加一笔
	bool dealCalculator(const sPanoramicBondDealUnit& unitD);//计算
	bool removeDeal(const sPanoramicBondDealUnit& unitD);	 //删减一笔

	bool IsCleanPrice() const { return strcmp(m_quotetype, "1") == 0; }  //净价
	bool IsFullPrice() const { return strcmp(m_quotetype, "2") == 0; }   //全价
	void Initial();

	CNewBondPanDeal& operator=(const sPanoramicBondDealUnit& unit){
		m_indexID = unit.m_indexID;
		m_updateTime = unit.m_updateTime;
		FIELDCOPY(m_bondCode, unit.m_bondCode);
		FIELDCOPY(m_bondkey, unit.m_bondkey);
		FIELDCOPY(m_listedmarket, unit.m_listedmarket);
		FIELDCOPY(m_price, unit.m_price);
		FIELDCOPY(m_cleanPrice, unit.m_cleanPrice);
		FIELDCOPY(m_yield, unit.m_yield);
		FIELDCOPY(m_id, unit.m_id);
		FIELDCOPY(m_dealStatus, unit.m_dealStatus);
		FIELDCOPY(m_preCloseYield, unit.m_preCloseYield);
		FIELDCOPY(m_preClosecleanPrice, unit.m_preClosecleanPrice);
		FIELDCOPY(m_withinPeriodDeal, unit.m_withinPeriodDeal);
		FIELDCOPY(m_listedFirstDeal, unit.m_listedFirstDeal);
		FIELDCOPY(m_quotetype, unit.m_quotetype);
		FIELDCOPY(m_exercise, unit.m_exercise);
		FIELDCOPY(m_OptionType, unit.m_OptionType);
		FIELDCOPY(m_preAdv, unit.m_preAdv);
		FIELDCOPY(m_liquidLevel, unit.m_liquidLevel);
		FIELDCOPY(m_liquid, unit.m_liquid);
		m_Redemption_No = unit.m_Redemption_No;

		float fYeild = atof(unit.m_yield);
		if (fYeild > 0.0001) { //根据产品需求,剔除收益率≤0的数据 笔数需要增加
			m_cdcGapPercent = unit.m_cdcGapPercent;
			m_cdcGapCleanPrice = unit.m_cdcGapCleanPrice;
			m_cdcGapBP = unit.m_cdcGapBP;
			m_closeGapPercent = unit.m_closeGapPercent;
			m_closeGapBP = unit.m_closeGapBP;
		}
		m_messBegin = unit.m_messBegin;
		//Initial();
		return *this;
	}

	int m_nCount;		//笔数
	int m_nCleanNumb;
	int m_nYeildNumb;	//净价数
	double m_dbHigh;	//最高
	double m_dbLow;		//最低
	double m_dbAdv;		//平均成交
	bool m_bCleanCal;
};

enum sortKey {
	emKey_Unkown, //未知
	emKey_Remain, //剩余期限
	emKey_Short,  //简称
	emKey_Count,  //成交笔数
	emKey_Adv,	  //平均成交
	emKey_Yes,	  //昨日成交
	emKey_High,	  //最高
	emKey_Low,	  //最低
	emKey_Up,	  //净价偏离(涨幅榜)
	emKey_UpBP,	  //偏离BP(涨幅榜)
	emKey_Down,	  //净价偏离(跌幅榜)
	emKey_DownBP, //偏离BP(跌幅榜)
	emKey_Price,  //价格
	emKey_Time	  //时间
};

class NewBondPanDealSorter {
public:
	NewBondPanDealSorter(int sortKey, bool desc) : m_sortKey(sortKey), m_desc(desc) {}
	bool operator()(const CNewBondPanDeal& left, const CNewBondPanDeal& right) {
		int ret = 0;
		switch (m_sortKey) {
		case emKey_Remain: {
			int64_t l = getRemainedDays(left.m_bondkey, left.m_listedmarket);
			int64_t r = getRemainedDays(right.m_bondkey, right.m_listedmarket);
			ret = int64Sort(l, r);
			break;
		}
		case emKey_Short:{
			const char* l = getBondShortName(left.m_bondkey, left.m_listedmarket);
			const char* r = getBondShortName(right.m_bondkey, right.m_listedmarket);
			ret = txtSort(l, r);
			break;
		}
		case emKey_Count:
			ret = intSort(left.m_nCount, right.m_nCount);
			break;
		case emKey_Adv:
			ret = floatSort(left.m_dbAdv, right.m_dbAdv);
			break;
		case emKey_Yes:
			ret = txtFloatSort(left.m_preAdv, right.m_preAdv);
			break;
		case emKey_High:{
			double l=0.0, r=0.0;
			if (left.IsCleanPrice() || left.IsFullPrice()) l = left.m_dbHigh;
			else l = left.m_dbLow;
			if (right.IsCleanPrice() || right.IsFullPrice()) r = right.m_dbHigh;
			else r = right.m_dbLow;
			ret = floatSort(l, r);
			break;
		}
		case emKey_Low: {
			double l = 0.0, r = 0.0;
			if (left.IsCleanPrice() || left.IsFullPrice()) l = left.m_dbLow;
			else l = left.m_dbHigh;
			if (right.IsCleanPrice() || right.IsFullPrice()) r = right.m_dbLow;
			else r = right.m_dbHigh;
			ret = floatSort(l, r);
			break;
		}
		case emKey_Up:
			ret = floatSort(left.m_cdcGapPercent, right.m_cdcGapPercent);
			break;
		case emKey_UpBP:
			ret = floatSort(left.m_cdcGapBP, right.m_cdcGapBP);
			break;
		case emKey_Down:
			ret = floatSort(left.m_cdcGapPercent * (-1), right.m_cdcGapPercent * (-1));
			break;
		case emKey_DownBP:
			ret = floatSort(left.m_cdcGapBP * (-1), right.m_cdcGapBP * (-1));
			break;
		case emKey_Price:
			ret = txtFloatSort(left.m_price, right.m_price);
			break;
		case emKey_Time:
			ret = timeSort(left.m_updateTime, right.m_updateTime);
			break;
		default:
			break;
		};
		return m_desc ? (ret>0) : (ret<0);
	}
private:
	const char* getBondShortName(const char* bondKey, const char* market) {
		CBondContainer& bc = CBondContainer::instance();
		int bondIndex = CBondContainer::instance().GetBondIndex(bondKey, market);
		if (!CBondContainer::instance().IsValidIndex(bondIndex)) return nullptr;
		const CBondInfo& bi = bc.ElementAtR(bondIndex);
		return bi.GetBondShortName();
	}
	int64_t getRemainedDays(const char* bondKey, const char* market) {
		CBondContainer& bc = CBondContainer::instance();
		int bondIndex = CBondContainer::instance().GetBondIndex(bondKey, market);
		if (!CBondContainer::instance().IsValidIndex(bondIndex)) return 0;
		const CBondInfo& bi = bc.ElementAtR(bondIndex);
		time_t serverTime = CSSVContainer::GetServerTime();
		return bi.GetRemainedDays(serverTime);
	}
	int int64Sort(int64_t l, int64_t r) {
		if (l < r) return -1;
		else if (l == r) return 0;
		else return 1;
	}
	int intSort(int l, int r) {
		if (l < r) return -1;
		else if (l == r) return 0;
		else return 1;
	}
	int txtSort(const char* l, const char* r) {
		if (!l || !r) return 0;
		return strcmp(l, r);
	}
	int txtFloatSort(const char* l, const char* r) {
		if (l && !r) return 1;
		if (!l && r) return -1;
		if (!l && !r) return 0;
		if (strlen(l) == 0 && strlen(r) > 0) return -1;
		if (strlen(l) > 0 && strlen(r) == 0) return 1;
		if (strlen(l) == 0 && strlen(r) == 0) return 0;
		return floatSort(atof(l), atof(r));
	}
	int floatSort(double l, double r) {
		const float EPSINON = 0.0000001f;
		if (l < r) return -1;
		else if ((l-r)>-EPSINON && (l-r)<EPSINON) return 0;
		else return 1;
	}
	int timeSort(time_t l, time_t r) {
		if (l < r) return - 1;
		else if (l == r) return 0;
		else return 1;
	}
private:
	int m_sortKey;
	bool m_desc;
};

class CreditDebtRankingData : public QObject{
Q_OBJECT
	enum emFstType {
		fst_Tab_20 = 0,//20日首次成交
		fst_Tab_List,
		fst_Tab_Max
	};
public:
	enum EmBondType {
		type_RankUp,		//按涨前20
		type_RankDown,		//按涨后20
		type_DeviateUp,		//按偏离值涨20
		type_DeviateDown,	//按偏离值涨后20
		type_FirstDeal,		//20日首次成交
		type_Active,		//活跃成交
		//type_FirstDealList//上市日首次成交
	};

	//首次成交筛选
	enum emFilterFstDeal {
		prod_All = 0,	//全部
		prod_Intel,		//利率
		prod_Short,		//短融
		prod_ZP,		//中票
		prod_Ent,		//企业债
		prod_Comp,		//公司债
		prod_PPN,		//PPN
		prod_NCD,		//NCD
		prod_Other,		//其他
		prod_Max,
	};

	CreditDebtRankingData();
	~CreditDebtRankingData() {}

signals:
	void newDataArrived();
public:
	void loadData();
	bool getTopDealData(std::vector<CNewBondPanDeal>& lstDeal, int bondType, int cunt = 20 /*前后数目*/, bool bNeedCount = false/*是否需要数目*/); //获取排名前20的信用债
	const std::list<std::string>& getFlash() const;

	////20日首次成交过滤筛选///////////////////////////////////////////////////
	void setFilter(const std::vector<int>& filter, int fltProd);
	void getFilter(std::vector<int>& filter);
	//////////////////////////////////////////////////////////////////////////

protected slots:
	void onDealPush(int funcId, QList<xQBPanoramicMarketStreamUnit> lstData);
	void onDataArrived();

private:
	bool verifyUpDown(const CNewBondPanDeal& panD, bool bCDC); //判断是否需要显示在涨跌幅榜中
	bool verifyFirstFilter(const CNewBondPanDeal& panD, bool bList/*是否上市日*/);
	void clearData();
	void sortListData();

private:
	int m_nFirstType = fst_Tab_20;							 //20日首次和上市日首次
	std::vector<int> m_filter;					 //20日首次成交筛选
	std::map<QString, CNewBondPanDeal> m_mapRank;//所有债券信息
	std::set<QString> m_setCreditBond;			 //所有信用债
	std::list<QString> m_lstRankUpDown;			 //按涨跌 与昨收对比
	std::list<QString> m_lstRankDeviate;		 //按偏离 与中债估值的对比
	std::list<QString> m_lstFirstDeal;			 //首次成交
	std::list<std::string> m_lstFlash;
};
